import type { WineCoolerController, WineCoolerSettingPosition } from './definition'
import { createBaseState, BaseGetters, BaseActions, createBaseApplianceControl } from '../BaseAppliance'
import { defineStore } from 'pinia'
import { useRemote, useWorker, wrapSafeActions } from '../base'
import { RemoteTypes } from '../base/remote'
import {
  FLEX_WINECOMPARTMENT,
  FLEX_WINECOMPARTMENT2,
  FLEX_WINECOMPARTMENT3,
  WINE_HUMIDITY_TOP,
  WINE_HUMIDITY_MIDDLE,
  WINE_HUMIDITY_BOTTOM,
  TEMPERATURE_KEY,
  WineCoolerHumidity,
} from '@/constants/Command'
import { getSetting, setSetting } from '@/api/appliance'

export enum CompartmentType {
  Top = 'top',
  Middle = 'middle',
  Bottom = 'bottom',
}
const CompartmentTemperatureKeys: Record<CompartmentType, string> = {
  [CompartmentType.Top]: FLEX_WINECOMPARTMENT,
  [CompartmentType.Middle]: FLEX_WINECOMPARTMENT2,
  [CompartmentType.Bottom]: FLEX_WINECOMPARTMENT3,
}
const CompartmentHumidityKeys: Record<CompartmentType, string> = {
  [CompartmentType.Top]: WINE_HUMIDITY_TOP,
  [CompartmentType.Middle]: WINE_HUMIDITY_MIDDLE,
  [CompartmentType.Bottom]: WINE_HUMIDITY_BOTTOM,
}

const CompartmentTemperatureFields: Record<CompartmentType, keyof WineCoolerController.State> = {
  [CompartmentType.Top]: 'top_temperature',
  [CompartmentType.Middle]: 'middle_temperature',
  [CompartmentType.Bottom]: 'bottom_temperature',
}
const CompartmentHumidityFields: Record<CompartmentType, keyof WineCoolerController.State> = {
  [CompartmentType.Top]: 'top_humidity',
  [CompartmentType.Middle]: 'middle_humidity',
  [CompartmentType.Bottom]: 'bottom_humidity',
}

export const createWineCoolerState: () => WineCoolerController.State = () => ({
  ...createBaseState(),
  /**
   * 温度单位
   */
  temperatureUnit: '',

  /**
   * 上部变温室 温度、湿度等级
   */
  top_temperature: null,
  top_humidity: null,

  /**
   * 中部变温室 温度、湿度等级
   */
  middle_temperature: null,
  middle_humidity: null,

  /**
   * 下部变温室 温度、湿度等级
   */
  bottom_temperature: null,
  bottom_humidity: null,

  /**
   * 当前设置的变温室相关数据 Setting
   */
  currentCompartmentType: null,
  currentTemperatureSetting: null,
  currentHumiditySetting: null,
})
export const WineCoolerGetters: WineCoolerController.Getters = {
  ...BaseGetters,
  // 当前设置的变温室 温度
  currentCompartmentTemperatureKey() {
    if (!this.currentCompartmentType) return ''
    return CompartmentTemperatureKeys[this.currentCompartmentType]
  },
  currentCompartmentTemperature() {
    if (!this.currentCompartmentType) return null
    const field = CompartmentTemperatureFields[this.currentCompartmentType]
    return this[field] as unknown as number
  },
  // 当前设置的变温室 湿度
  currentCompartmentHumidityKey() {
    if (!this.currentCompartmentType) return ''
    return CompartmentHumidityKeys[this.currentCompartmentType]
  },
  currentCompartmentHumidity() {
    if (!this.currentCompartmentType) return null
    const field = CompartmentHumidityFields[this.currentCompartmentType]
    return this[field] as unknown as WineCoolerHumidity
  },
}
export const WineCoolerActions: WineCoolerController.Actions = wrapSafeActions<
  WineCoolerController.Store,
  WineCoolerController.Actions
>({
  ...BaseActions,
  /**
   * 加载当前变温室设置
   */
  async loadCurrentCompartmentSetting() {
    if (!this.currentCompartmentType) return

    const haId = this._datasource.haId
    const temperatureKey = this.currentCompartmentTemperatureKey
    const humidityKey = this.currentCompartmentHumidityKey
    const [tempRes, humidityRes] = await Promise.all([getSetting(haId, temperatureKey), getSetting(haId, humidityKey)])
    this.currentTemperatureSetting = tempRes.data
    this.currentHumiditySetting = humidityRes.data
  },
  /**
   * 设置当前变温室温度
   */
  async setCurrentTemperature(temperature: number) {
    if (!this.currentCompartmentTemperatureKey) return

    const haId = this._datasource.haId
    const temperatureKey = this.currentCompartmentTemperatureKey
    await setSetting(haId, temperatureKey, temperature, {
      others: {
        unit: this.temperatureUnit,
      },
    })
  },
  async decreaseCurrentTemperature() {
    if (!this.currentCompartmentTemperature) return

    const currentTempValue = this.currentCompartmentTemperature
    const stepsize = this.currentTemperatureSetting?.constraints?.stepsize || 1
    const newTempValue = currentTempValue - stepsize
    await this.setCurrentTemperature(newTempValue)
  },
  async increaseCurrentTemperature() {
    if (!this.currentCompartmentTemperature) return

    const currentTempValue = this.currentCompartmentTemperature
    const stepsize = this.currentTemperatureSetting?.constraints?.stepsize || 1
    const newTempValue = currentTempValue + stepsize
    await this.setCurrentTemperature(newTempValue)
  },
  /**
   * 设置当前变温室湿度
   */
  async setCurrentHumidity(humidity: WineCoolerHumidity) {
    if (!this.currentCompartmentHumidityKey) return

    const haId = this._datasource.haId
    const humidityKey = this.currentCompartmentHumidityKey
    await setSetting(haId, humidityKey, humidity)
  },
})

/**
 * 组合API
 */
const useStore = defineStore<
  'WineCooler',
  WineCoolerController.State,
  WineCoolerController.Getters,
  WineCoolerController.Actions
>('WineCooler', {
  state: createWineCoolerState,
  getters: WineCoolerGetters,
  actions: WineCoolerActions,
})

// 组件使用
export function useWineCoolerControl(): WineCoolerController.Control {
  const store = useStore() as WineCoolerController.Store
  const worker = useWorker(store)
  const remote = useRemote(store)
  return { store, worker, remote }
}

// 页面使用
export function createWineCoolerControl(
  control: WineCoolerController.Control = useWineCoolerControl()
): WineCoolerController.Control {
  const { store, worker, remote } = control

  createBaseApplianceControl(control, { remoteType: RemoteTypes.Inhouse })

  worker.onLoad(async () => {
    await Promise.all([remote.loadAllSetting()])
  })

  useWineCoolerEffects(control)

  return control
}

function useWineCoolerEffects(control: WineCoolerController.Control) {
  useWineCoolerBinding(control)
}

function useWineCoolerBinding(control: WineCoolerController.Control) {
  const { worker } = control

  /**
   * 温度单位
   */
  worker.useGetValueBinding('temperatureUnit', {
    key: TEMPERATURE_KEY,
    from: 'setting',
    patcher(patchState, reference) {
      patchState.temperatureUnit = (reference.item.displayvalue as string | undefined) || '°C'
    },
  })

  /**
   * 上部变温室 温度、湿度等级
   */
  worker.useGetValueBinding('top_temperature', {
    key: FLEX_WINECOMPARTMENT,
    from: 'setting',
  })
  worker.useGetValueBinding('top_humidity', {
    key: WINE_HUMIDITY_TOP,
    from: 'setting',
  })
  /**
   * 中部变温室 温度、湿度等级
   */
  worker.useGetValueBinding('middle_temperature', {
    key: FLEX_WINECOMPARTMENT2,
    from: 'setting',
  })
  worker.useGetValueBinding('middle_humidity', {
    key: WINE_HUMIDITY_MIDDLE,
    from: 'setting',
  })

  /**
   * 下部变温室 温度、湿度等级
   */
  worker.useGetValueBinding('bottom_temperature', {
    key: FLEX_WINECOMPARTMENT3,
    from: 'setting',
  })
  worker.useGetValueBinding('bottom_humidity', {
    key: WINE_HUMIDITY_BOTTOM,
    from: 'setting',
  })
}
